#!/usr/bin/env python
# -*- coding: utf-8 -*-

from typing import Any

from cta.interface.action.close_position.abstract_close_not_main_contract_action import \
    AbstractCloseNotMainContractAction
from web.constants.close_position_reason import ClosePositionReason
from web.constants.direction import Direction
from web.domain.responsibility_chain_dto import ResponsibilityChainDto
from web.manager.log_manager import LogManager
from web.models import CommodityFutureInfo
from web.models.commodity_future_date_contract_data import CommodityFutureDateContractData
from web.models.quant2_account import Quant2Account
from web.models.quant2_commodity_future_filter import Quant2CommodityFutureFilter
from web.models.quant2_commodity_future_transaction_record import Quant2CommodityFutureTransactionRecord
from web.util.commodity_future_code_util import CommodityFutureCodeUtil

Logger = LogManager.get_logger(__name__)

class Quant2CloseNotMainContractAction(AbstractCloseNotMainContractAction):
    """
    动量因子策略，平仓非主力合约
    """

    def exec(self, responsibility_chain_dto: ResponsibilityChainDto = None) -> Any:
        Logger.info("动量因子策略，平仓非主力合约")

        transaction_date: str = responsibility_chain_dto.transaction_date

        # 查询quant2_c_f_filter表中所有记录
        quant2_commodity_future_filter_list: list[Quant2CommodityFutureFilter] = self.quant2_commodity_future_filter_dao.find_all()

        # 判断#quant2_c_f_filter表中是否有记录
        if quant2_commodity_future_filter_list is None or len(quant2_commodity_future_filter_list) == 0:
            Logger.warning("quant2_c_f_filter表中没有记录，无法平仓非主力合约")
            super().next(responsibility_chain_dto)
            return

        quant2_account_list: list[Quant2Account] = self.quant2_account_dao.find_all()
        for quant2_account in quant2_account_list:

            # 查询某个账户的所有持仓记录
            quant2_commodity_future_transaction_record_list: list[Quant2CommodityFutureTransactionRecord] = self.quant2_commodity_future_transaction_record_dao.find_by_account_name_and_not_close_position(quant2_account.account_name)

            # 如果这个账号没有持仓记录，则跳过
            if quant2_commodity_future_transaction_record_list is None or len(quant2_commodity_future_transaction_record_list) == 0:
                Logger.warning("账号[%s]没有持仓记录，不用平仓非主力合约", quant2_account.account_name)
                continue

            for quant2_commodity_future_transaction_record in quant2_commodity_future_transaction_record_list:
                # 如果这条持仓记录已经不是主力合约，则平仓
                if quant2_commodity_future_transaction_record.code not in list(map(lambda x: x.code, quant2_commodity_future_filter_list)):
                    Logger.info("期货[%s]不再是主力合约，因此平仓", quant2_commodity_future_transaction_record.code)

                    # 查询收盘价
                    commodity_future_date_contract_date: CommodityFutureDateContractData = self.commodity_future_date_contract_data_dao.find_by_code_and_transaction_date(quant2_commodity_future_transaction_record.code, transaction_date)
                    if commodity_future_date_contract_date is None:
                        Logger.warning("期货[%s]在日期[%s]没有交易记录，查询前一个交易日的记录", quant2_commodity_future_transaction_record.code, transaction_date)
                        commodity_future_date_contract_date = self.commodity_future_date_contract_data_dao.find_last_commodity_future_date_contract_data_by_code_and_date(quant2_commodity_future_transaction_record.code, transaction_date)

                    # 查询期货信息
                    filter_dict = {'code__iexact': CommodityFutureCodeUtil.code_to_contract_code(quant2_commodity_future_transaction_record.code)}
                    commodity_future_info: CommodityFutureInfo = self.commodity_future_info_dao.find_one(filter_dict, dict(), list())

                    # 平仓（更新记录）
                    self.quant2_commodity_future_transaction_record_dao.update_when_close_position(quant2_commodity_future_transaction_record.direction,
                        transaction_date, commodity_future_date_contract_date.close_price, commodity_future_info,
                        quant2_commodity_future_transaction_record.buy_lot if quant2_commodity_future_transaction_record.direction == Direction.Up else quant2_commodity_future_transaction_record.sell_lot,
                        ClosePositionReason.Close_Not_Main_Contract, quant2_commodity_future_transaction_record.id_)

        super().next(responsibility_chain_dto)